﻿using System;
using System.Globalization;
using SpecFlowTfsLinker.Cleaner;

namespace SpecFlowTfsLinker.Printer
{
    [Serializable]
    public class ParameterPrinter
    {
        private const string IntStringType = "int";
        private const string FloatStringType = "float";
        private const string BoolStringType = "bool";
        private const string DateTimeStringType = "DateTime";
        private const string StringStringType = "string";

        private readonly ICleaner _cleaner;
        private readonly string _initialParameter;
        private string _cleanedParameter;
        private string _displayType;
        private Type _type;

        public ParameterPrinter(string parameter)
        {
            _initialParameter = parameter;
            _cleaner = new ParameterCleaner(_initialParameter);
        }

        public string DisplayType
        {
            get
            {
                if (string.IsNullOrEmpty(_displayType))
                    _displayType = GetStringFromType();
                return _displayType;
            }
        }

        public string Parameter
        {
            get
            {
                if (string.IsNullOrEmpty(_cleanedParameter))
                    _cleanedParameter = _cleaner.Clean();
                return _cleanedParameter;
            }
        }

        public Type Type
        {
            get { return _type ?? (_type = TryParse()); }
        }

        private string GetStringFromType()
        {
            if (Type == typeof (int))
                return IntStringType;
            if (Type == typeof (float))
                return FloatStringType;
            if (Type == typeof (DateTime))
                return DateTimeStringType;
            if (Type == typeof (bool))
                return BoolStringType;
            return StringStringType;
        }

        private Type TryParse()
        {
            int number;
            float floatNumber;
            DateTime date;
            bool boolean;
            Type type;

            if (int.TryParse(Parameter, out number))
                type = typeof (int);
            else if (float.TryParse(Parameter, NumberStyles.Any, CultureInfo.InvariantCulture, out floatNumber))
                type = typeof (float);
            else if (DateTime.TryParse(Parameter, DateTimeFormatInfo.CurrentInfo, DateTimeStyles.None, out date))
                type = typeof (DateTime);
            else if (Boolean.TryParse(Parameter, out boolean))
                type = typeof (bool);
            else type = typeof (string);
            return type;
        }
    }
}